﻿//-----------------------------------------------------------------------
// <copyright file="PivotTablebuilder.cs" company="Forebrain Technology, LLC">
//
// Copyright (c) Forebrain Technology, LLC. All rights reserved.
// 
// This source code is released under the Microsoft Public License (Ms-PL).
//
// </copyright>
//-----------------------------------------------------------------------
namespace PivotCollectionTools.Library
{
    using System;
    using System.Globalization;
    using System.Linq;
    using PivotCollectionTools.Data;
    using PivotCollectionTools.Xml;

    /// <summary>
    /// Creates Pivot Collection XML from Pivot Table and create a Pivot Table from XML. 
    /// </summary>
    public class PivotTableBuilder
    {
        /// <summary>
        /// Gets the last XML read.
        /// </summary>
        /// <value>The last XML read of the pivot table builder.</value>
        public PivotXml LastXmlRead { get; private set; }

        /// <summary>
        /// Reads from a Pivot Collection XML file and populates the specified <see cref="PivotTable"/>.
        /// </summary>
        /// <param name="table">The specified table to populated data with.</param>
        /// <param name="fileName">Name of the file to read from.</param>
        public PivotTable ReadFromXml(string fileName)
        {
            PivotTable table = new PivotTable();
            this.LastXmlRead = PivotXml.CreateFromXml(fileName);

            foreach (var facetCategory in this.LastXmlRead.FacetCategories)
            {
                PivotTableCategory tableCategory;

                switch (facetCategory.FacetType)
                {
                    case FacetDataType.String:
                    default:
                        tableCategory = new PivotTableCategory(facetCategory.Name, PivotTableCellType.Text);
                        break;
                    case FacetDataType.Number:
                        tableCategory = new PivotTableCategory(facetCategory.Name, PivotTableCellType.Number);
                        break;
                    case FacetDataType.DateTime:
                        tableCategory = new PivotTableCategory(facetCategory.Name, PivotTableCellType.DateTime);
                        break;
                }

                tableCategory.Format = facetCategory.Format;
                tableCategory.IsFilterVisible = facetCategory.IsFilterVisible;
                tableCategory.IsWordWheelVisible = facetCategory.IsWordWheelVisible;
                tableCategory.IsMetadataVisible = facetCategory.IsMetadataVisible;
                
                table.Categories.Add(tableCategory);

                table.AddColumn(facetCategory.Name);
            }

            foreach (var item in this.LastXmlRead.ItemList[0].Items)
            {
                AddItem(table, item);
            }

            return table;
        }

        /// <summary>
        /// Gets the string values from the specified item's facet for the specified facetCategory
        /// and populated the associated cells in the data row.
        /// </summary>
        /// <param name="item">The item to get the facet data from.</param>
        /// <param name="dataRow">The data row to populate.</param>
        /// <param name="categoryName">Name of the facetCategory.</param>
        private static void GetStringValue(Item item, PivotTableRow dataRow, string categoryName)
        {
            Facet stringFacet = item.Facets[categoryName];
            if (stringFacet == null)
            {
                return;
            }

            if (!stringFacet.Text.Any())
            {
                return;
            }

            string columnName = categoryName;
            for (int counter = 0; counter < stringFacet.Text.Count(); counter++)
            {
                if (counter > 0)
                {
                    columnName = string.Concat(categoryName, " ", counter);
                }

                dataRow.Cells[columnName].Value = stringFacet.Text[counter].Value;
            }
        }

        /// <summary>
        /// Gets the number value.
        /// </summary>
        /// <param name="item">The collection item.</param>
        /// <param name="dataRow">The data row to populate.</param>
        /// <param name="categoryName">Name of the facetCategory.</param>
        private static void GetNumberValue(Item item, PivotTableRow dataRow, PivotTableCategory category)
        {
            string categoryName = category.Name;
            Facet itemFacet = item.Facets[categoryName];
            if (itemFacet == null)
            {
                dataRow.Cells[category.Columns[0].Name].Value = "0.0";
                return;
            }

            if (!itemFacet.Number.Any())
            {
                dataRow.Cells[categoryName].Value = "0.0";
                return;
            }

            string columnName = categoryName;

            if (category.Columns.Count == 1)
            {
                PivotTableCell cell = dataRow.Cells[categoryName];
                cell.Value = itemFacet.Number[0].Value.ToString(CultureInfo.CurrentCulture);
            }
            else
            {
                for (int counter = 0; counter < itemFacet.Number.Count(); counter++)
                {
                    columnName = string.Concat(categoryName, " ", counter + 1);

                    try
                    {
                        PivotTableCell cell = dataRow.Cells[columnName];
                        cell.Value = itemFacet.Number[counter].Value.ToString(CultureInfo.CurrentCulture);
                    }
                    catch (Exception ex)
                    {
                        Console.Write(ex.Message);
                    }
                }
            }
        }

        /// <summary>
        /// Gets the date value.
        /// </summary>
        /// <param name="item">The collection item.</param>
        /// <param name="dataRow">The data row to populate.</param>
        /// <param name="categoryName">Name of the facetCategory.</param>
        private static void GetDateValue(Item item, PivotTableRow dataRow, string categoryName)
        {
            Facet dateTimeFacet = item.Facets[categoryName];
            if (dateTimeFacet == null)
            {
                return;
            }

            if (!dateTimeFacet.DateTime.Any())
            {
                return;
            }

            string columnName = categoryName;

            for (int counter = 0; counter < dateTimeFacet.DateTime.Count(); counter++)
            {
                if (counter > 0)
                {
                    columnName = string.Concat(categoryName, counter);
                }

                dataRow.Cells[columnName].Value = dateTimeFacet.DateTime[counter].Value.ToString();
            }
        }

        /// <summary>
        /// Gets the facet value count.
        /// </summary>
        /// <param name="collectionItem">The collection item.</param>
        /// <param name="category">The category.</param>
        /// <returns>The number of Facet values for a collectio item.</returns>
        private static int GetFacetValueCount(Item collectionItem, PivotTableCategory category)
        {
            if (collectionItem.Facets.Count == 0)
            {
                return 0;
            }

            Facet itemFacet = collectionItem.Facets[category.Name];
            if (itemFacet == null)
            {
                return 0;
            }

            switch (category.ValueType)
            {
                case PivotTableCellType.Text:
                    if (itemFacet.Text == null)
                    {
                        return 0;
                    }

                    return itemFacet.Text.Count();
                case PivotTableCellType.Number:
                    if (itemFacet.Number == null)
                    {
                        return 0;
                    }

                    return itemFacet.Number.Count();
            }

            return 0;
        }

        /// <summary>
        /// Adds the specified item to the table.
        /// </summary>
        /// <param name="item">The item to add to the table.</param>
        /// <returns>A <see cref="PivotTableRow"/> that represents the item add to the table.</returns>
        private static PivotTableRow AddItem(PivotTable table, Item item)
        {
            int categoryCount = table.CategoryCount;
            for (int counter = 0; counter < categoryCount; counter++)
            {
                PivotTableCategory category = table.Categories[counter];
                string baseColumnName = category.Name;

                int x = GetFacetValueCount(item, category);
                if (x > 1)
                {
                    for (int facetCounter = 0; facetCounter < x; facetCounter++)
                    {
                        string newColumn = string.Concat(baseColumnName, " ", facetCounter + 1);
                        if (facetCounter == 0 && table.Columns.Contains(baseColumnName))
                        {
                            var column = table.Columns[baseColumnName].Name = string.Concat(baseColumnName, " 1");
                        }
                        else
                        {
                            if (!table.Columns.Contains(newColumn))
                            {
                                table.AddColumn(category.Name);
                            }
                        }
                    }
                }
            }

            PivotTableRow dataRow = table.NewRow();
            dataRow.Cells["Name"].Value = item.Name;
            dataRow.Cells["Href"].Value = item.Href;
            dataRow.Cells["Description"].Value = item.Description;
            foreach (var category in table.Categories)
            {
                if (!category.DataBound)
                {
                    continue;
                }

                switch (category.ValueType)
                {
                    case PivotTableCellType.Text:
                        GetStringValue(item, dataRow, category.Name);
                        break;
                    case PivotTableCellType.Number:
                        try
                        {
                            GetNumberValue(item, dataRow, category);
                        }
                        catch (Exception ex)
                        {
                            Console.Write(ex.Message);
                        }

                        break;
                    case PivotTableCellType.DateTime:
                        GetDateValue(item, dataRow, category.Name);
                        break;
                }
            }

            return dataRow;
        }
    }
}
